home  previous   next  contents

Shout3D™ 2.0 Specification

 

Programming API

5.1 Introduction and Contents

This document describes an application programmer interface, or API, for the Shout3D specification. The API is designed to meet a set of functional requirements and design goals. This document contains the following sections:

5.1. Introduction and Contents
5.2. Functional Requirements
5.3. Design Goals
5.4. Functional Description
5.4.1. Classes
5.4.1.1. Field Classes
5.4.1.2. Node Classes
5.4.1.3. DeviceInput Classes
5.4.1.4. CoreShout3DException
5.4.2. Interfaces
5.4.2.1. UsageTypes
5.4.2.2. FieldObserver
5.4.2.3. Searcher
5.4.2.4. Picker
5.4.2.5. Renderer and RenderObserver
5.4.2.6. ResourceListener and ResourceObserver
5.4.2.7. DeviceListener and DeviceObserver
5.4.2.8. CoreShout3DViewer and Clock

Three descriptions of the API are provided, in this document, an IDL document, and a set of Java Documentation:

5.2 Functional Requirements

The following is the set of tasks that the API must support. This set is necessary and sufficient for enabling programmers to write applications that create and interact with scene graphs, windows and devices.

  1. Access Nodes and Fields:
    1. Create nodes
    2. Access and modify fields within nodes
    3. Arrange nodes in a hierarchy
    4. Introspect nodes to find out about their fields
    5. Access nodes by name
  2. Operate on Scene Graphs:
    1. Load scenes into the application
    2. Render scene graphs
    3. Intersect rays with objects in scene graphs
    4. Search for nodes within scene graphs
    5. Retrieve transformation matrices between parent/child levels of the hierarchy
  3. Communicate:
    1. React to external events (device events, window iconify/deiconify)
    2. Find out when the implementation has completed requests (rendering, asset loading, file reading)
    3. Handle Errors (supported, but not automatic)
    4. Notify when nodes have changed.
  4. Extend:
    1. Create new kinds of fields
    2. Create new kinds of nodes
    3. Create new kinds of field usage

Most of the requirements above are self explanatory. The following details should clarify or justify those which are less clear.

Introspect nodes: When presented with a node of unknown type, a programmer should be able to determine the type of the node, an enumeration and description of that node's fields, and the ability to retrieve a reference to each of that node's fields. In future releases, Shout3D may add new types of fields. (See field classes).

Handle Errors: Error handling must be enabled by the API. However not all implementations will wish to pay for the overhead of automatic error handling. Therefore, the necessary information and hooks are provided, but an actual error checking mechanism is not included as a requirement (See error checking).

Notify: When values of fields change, applications should be able to respond to those changes. The API provides a way for fields to notify other objects when their values change using FieldObservers.

5.3 Design Goals

In creating an API that satisfies the above functional requirements, the following design goals should be considered:

5.3.1 Completeness

The API should meet all of the functional requirements. Programmers should be able to access all the functionality without requiring additional support from a given implementation. This does not mean that the API should contain a way to do everything. But the API must be enabling: programmers should feel that they have access and control of all aspects of the Core.

5.3.2 Compactness

Only functionality that is required from every implementation is to be included in the Core API. Every interface, class, method and public member variable in the API must support one of the functional requirements. A compact API has the following benefits:

Ease of Implementation: If the set of Core field and node types is small, and the API is compact, there are fewer methods, classes, and interrelationships to implement. Any capable 3D programmer should be able to comprehend the entirety of the specification and imagine a clear path for implementation.

Flexibility: Each required class or method in an API reduces the number of paths toward implementation. There is at least some small implementation bias inherent in any such decision. The more compact the API is, the smaller the bias and the greater the flexibility for those implementing it to use their own special approaches and techniques.

Small Code Footprints: Only if the API is compact can implementations be compact. By keeping the requirements to a bare minimum, the API allows for tiny implementations. For example Shout3D, a Java implementation, is less than 75K in size.

5.3.3 Clarity

The API should be easy to read, understand, and remember.

5.3.4 Extensibility

The Core API is minimal, yet programmers are to be able to create new Node classes and applets based on it; hence, the API must provide straightforward ways to add extensions. It should be easy to add new classes of nodes that work with the rest of the system.

In addition, the API should be implementable in a variety of programming languages. Hence, it is important that no overloading of methods, or operator overloading, be used. Such constructs are not permitted in all programming languages.

5.3.5 Speed

The API must accommodate implementations that wish to run as quickly as possible. This means that the API must provide fast access to the data in scene graphs, avoiding extra layers of accessor methods wherever possible. It also means that the API must not force implementations to use particular patterns of node traversal or access in performing operations on scene graphs.

5.4 Functional Description

The Shout3D API is comprised of the following sets of classes and interfaces. Alternate, but equivalent, definitions of the API may be found in the IDL and JavaDoc sections.

5.4.1 Functional Description: Classes

5.4.1.1 Field Classes

Fields store the data that parameterize nodes.

Fields are classes: Fields are implemented as a hierarchy of classes, with methods to get and set their values.

Fields allow introspection: To enable programmers to work with fields without prior knowledge of a field's type, the API requires methods that support introspection. The requirements here are to be able to retrieve the field's type and to query whether the field is derived from a given type.

Fields notify, and may be observed for changes: The FieldObserver interface allows fields to be monitored for changes. The base class Field implements methods for adding and removing FieldObservers to a set of registered observers. When a field's value changes through its setValue (or set1Value in the case of ArrayFields) method, it will notify each registered FieldObserver by invoking its onFieldChanged method. To insure that behavior is deterministic, the set of registered FieldObservers is always processed in the order in which it was registered.

Field Usages: Fields may be used for storing many different kinds of information. Although individual field types are not provided to handle every particular kind of information, each type of node does store an intended use for each of its fields. For example, a node might use a FloatArrayField to store any of a coordinate, a set of coordinates, a rotation, a set of rotations, etc. Knowledge of this intended use is needed to enable programmers to perform error-checking of field values. For an enumeration of the provided set of field usages, see 3.4, Field Usages and 5.3.4, Usage Types.

Creating New Field Classes: The set of field classes is extensible. The only requirement of the API are that the new field class be subclassed from one of the twelve non-abstract classes defined in the core. New field may not be subclassed directly from the abstract classes Field and ArrayField.

Abstract Class: Field

The Field class is the abstract base class for Shout3D's twelve field classes. It contains the following:

	member variables
        owner       is a reference to the node that owns the field.
        usage       is the value of the field usage type imposed upon
                    the field by its owner node.
	methods
        getName     will return a string corresponding to the owner node's
                    name for this field. For example, Material node's 
                    diffuseColor field will return the name "diffuseColor".
        getTypeName returns a string denoting the field's type.
        isOfType    returns whether the field is of a class derived
                    from (or exactly matching) the type of the input
                    parameter.					 
        addFieldObserver     Adds a FieldObserver to watch this field.
        removeFieldObserver  Removes a FieldObserver from the list of 
                             registered observers.  Following this, the 
                             FieldObserver will no longer monitor the field.

Non-Array Classes derived from Field:

There are six non-abstract classes derived from the abstract class Field that are not derived from ArrayField: BooleanField, DoubleField, FloatField, IntField, NodeField, and StringField. Each of these stores a different kind of value (see Field Reference for an exhaustive listing). Each of these classes inherits the member variables and methods of the abstract Field, and adds the following:

	methods
        getValue   Returns the current value of the field.
        setValue   Sets the value of the field from the input argument.
                   After this, notifies all registered FieldObservers.

Classes derived from ArrayField:

The abstract class ArrayField is a subclass of Field. There are six non-abstract classes derived from the ArrayField: BooleanArrayField, DoubleArrayField, FloatArrayField, IntArrayField, NodeArrayField, and StringArrayField. Each of these stores an array containing a different kind of value (see Field Reference for an exhaustive listing). All ArrayFields inherit the member variables and methods of the Field class, and add the following:

	methods
           getLength   returns the number of elements currently in the 
                       array of values.
           getValue    Returns the current value of the field as a 
                       reference to the array.  Returns a reference to the
                       real information, not a copy. If an application
                       changes the data, it must notify the field by 
                       making a subsequent call to setValue.
           setValue    Sets the value of the field from the input argument.
                       Does not create a copy of the input, but refers
                       to the same array in memory. Following this, 
                       notifies all registered FieldObservers.
           set1Value   Sets a single value in the array from the input 
                       argument.  If the specified index is out of range,
                       throws a CoreShout3DException. Otherwise, sets the 
                       value and notifies all registered FieldObservers.
  

5.4.1.2 Node Classes

As described in the Node Reference, each type of node has a set of fields and semantics describing how it behaves when rendered. The API for nodes provides the minimal set of requirements to allow implementations to access those fields and achieve those behaviors.

Nodes contain fields: Each type of node has a set of fields to hold its unique data. The API allows fast and direct access to those fields without the use of methods by exposing them as public member variables.

Nodes allow introspection: To enable programmers to work with nodes without prior knowledge of a node's type, the API requires methods that support introspection. The requirements here are to be able to retrieve the node's type, to query whether the node is derived from a given type, to retrieve an enumeration of the node's fields, and to retrieve references to the individual fields.

Nodes have names: Nodes may be named. The API allows programmers to set and retrieve the name of a node.

Nodes are required to do nothing else! There are no other requirements on nodes. This leaves implementations complete freedom in how they choose to achieve implement functionality such as rendering and picking. This functionality may live inside or outside of the nodes themselves.

Creating New Node Classes: The set of node classes is extensible. The only requirements of the API are that the new node class:

  1. Be subclassed from an existing node class
  2. Use the existing field classes to add any needed fields.

Abstract Node Classes: Shout3D includes five abstract node classes, Bindable, Geometry, Interpolator, Light, and Texture. (See also 4.3, Abstract Node Classes). These serve to lend structure to the class hierarchy, and to assist in specifying specific nodes that may be included in a NodeField (see 3.5.7, Node Usage Types).

Abstract Class: Node

The Node class is the abstract base class for all Shout3D's other node classes. It contains no member variables and the following methods:

	methods
           getTypeName	  returns a string denoting the node's type.
           isOfType	  returns whether the node is of a class derived
			  from (or exactly matching) the type of the input
			  parameter.
           getDEFName        returns the name of the node.
           setDEFName        sets the name of the node.
           getNumFields      returns the number of fields owned by the node.
           getFieldByIndex   returns a reference to a field, given an
			     enumeration index. Throws an exception if the
		 	     given index is out of range.
           getField       returns a reference to a field, given a string
			  corresponding to the field's name. Throws an
			  exception if the string does not correspond to a
			  field owned by the node.
           getFieldName	  returns the name of a given field. Throws an
			  exception if the given field is not owned by the
			  node.
           getViewer	  returns the Shout3DViewer being used to display this node.
           setViewer	  establishes the Shout3DViewer being used to display this node.
		

Abstract Node Classes derived from Node:

The five abstract classes Bindable, Light, Geometry, Interpolator, and Texture are derived from Node. The Bindable, Light, and Interpolator classes each add fields as member variables. The others add no members or methods.

Class Group, derived from Node:

The Group class is derived from Node. It adds a children field member variable and one method:

	methods
		addChildren      add children to the group node.
		getInverseMatrix returns a matrix that transforms from the 
			         coordinate above the node to the coordinate 
			         space below the node.
		getMatrix        returns a matrix that transforms from the 
			         coordinate below the node to the coordinate 
			         space above the node.
		removeChildren   removes children from the group node.

Classes derived from Group:

The Billboard and Transform classes are derived from Group. They reimplement the getMatrix and getInverseMatrix method to return a matrix that reflects the field values, and in the case of Billboard, the orientation of its local space with respect to that of the viewpoint. The Anchor and TouchSensor classes are also derived from Group, but do not affect the transformation matrix, and so do not reimplement getMatrix.

Class TimeSensor, derived from Node:

The TimeSensor class is derived from Node. It has nine fields and the following three methods:

	methods
           start         starts this TimeSensor by setting the startTime
			 field to the current absolute time.
           stop          stops this TimeSensor by setting the 
			 stopTime field to the current absolute time.
           setPaused     pauses or unpauses this TimeSensor according
			 to the passed in boolean value.  Calling 
			 setPaused(false)on a TimeSensor which is 
			 not paused has no effect.
   		

All other Classes derived from Node:

All other classes do no more than add new fields to their parent classes as described in the Node Reference. No other classes add required methods or member variables.

5.4.1.3 DeviceInput classes

DeviceInput classes allow response to system-dependent device inputs: Viewers typically receive input from various devices. These include the mouse, keyboard, and window. The Shout3D API contains system-independent classes for specifying such input.

DeviceInput classes contain details: Each subclass of DeviceInput adds information detailing the particulars about the input that was received. For example, the MouseInput class contains x and y locations, as well as specification of DOWN, UP, MOVE, DRAG, ENTER, or EXIT input.

DeviceInput classes may be extended: The Core API provides DeviceInput subclasses for monitoring input from the Mouse, Keyboard and Window. Other subclasses may be created to express other devices, such as a joystick.

Programmers can be notified when device input is received: Each viewer has a DeviceListener that monitors input from devices. Programmers can register DeviceObservers to receive callbacks each time a DeviceListener receives input.

Abstract Class: DeviceInput

The DeviceInput class is the abstract base class for Shout3D's three DeviceInput classes. It contains the following:

	member variables
           timeStamp             is the time at which the input was received.
           modifier key masks:   ALT_MASK, CTRL_MASK, META_MASK, SHIFT_MASK
           modifiers             what modifiers were specified. Values may 
				 and'ed with the key masks to determine if 
				 modifier keys were pressed when the input
				 was received. For example, in java notation,
				 the test ((myModifier & ALT_MASK) != 0) will
				 be true if the ALT key was pressed.
	methods
           getTypeName returns a string denoting the deviceInput's type.
           isOfType    returns whether the deviceInput is of a class derived
                       from (or exactly matching) the type of the input 
                       parameter.

MouseInput class:

The MouseInput class describes input from a mouse. It adds the following to the base class:

	member variables
           mouse input types:    DOWN, UP, MOVE, DRAG, ENTER, EXIT
           which 	         which type of input was received 
                                 (DOWN, UP, MOVE, DRAG, ENTER, or EXIT)
           x                     the x location of the pixel below the cursor.
           y  			 the y location of the pixel below the cursor

KeyboardInput class:

The KeyboardInput class describes input from the keyboard. It adds the following to the base class:

	member variables
           keyboard input types: DOWN, UP
           action key constants: DOWN, END, F1, F2, F3, F4, F5, F6, F7, F8,
			         F9, F10, F11, F12, HOME, INSERT, LEFT, 
			         NUM_LOCK, PAUSE, PGDN, PGUP, PRINT_SCREEN,
			         RIGHT, SCROLL_LOCK, UP
           which 	         which type of input was received (DOWN or UP)
           key   	         what key was pressed
	        

WindowInput class:

The WindowInput class describes input from the window. It adds the following to the base class:

	member variables
		window input types: CLOSE, ICONIFY, DEICONIFY
		which               which type of input was received (CLOSE, 
		                    ICONIFY, or DEICONIFY)

5.4.1.4 CoreShout3DException Class

The API must provide at least minimal support for error checking. A standard way to check for errors while executing methods is through exceptions. To keep the API lightweight, only one exception class is required. Implementations are free to extend CoreShout3DException to provide finer-grain error feedback. The CoreShout3DException class has no methods or member variables.

5.4.2 Functional Description: Interfaces

5.4.2.1 Usage Types Interface

Usage types denote semantics: Usage types allow nodes to denote specific ways in which their fields are to be used. (See 3.4, Field Usages)

Usage types are the same for all node instances: Every instance of a node will set the same usage on a given field. For example, every instance of a Material node will have a usage of COLOR for its diffuseColor field.

Usage types must be set: In Shout3D, all implementations must set the usage types for every field in every node.

Usage types enable optional error-checking: Implementations are not required to check that field values fall within a valid value range. However, since it is a requirement that usage types be set for all fields, those implementations that wish to check valid ranges will have the required information readily available; each field's usage type may be retrieved by examining the member variable usage.

Usage types enable data compression: Data compression is not part of the Shout3D specification. However, because usage types are specified for all fields, data compression schemes may take advantage of them in compressing field data.

Creating New Usage Types: Implementations are free to add new field usage types for any new node classes they define.

Members: The UsageTypes interface has twenty-nine static final member variables, one for each of the predefined field usage types. (See also 3.4, Field Usages) These are:

	member variables
		ANY, APPEARANCE_NODE, COLOR, COLOR_ARRAY, COLOR_NODE,
		COORD3, COORD3_ARRAY, COORDINATE_NODE, DIRECTION,
		FIELD_OF_VIEW, GEOMETRY_NODE, INDEX_ARRAY, LINE_INDEX_ARRAY,
		MATERIAL_NODE, NON_NEGATIVE_DOUBLE, NON_NEGATIVE_FLOAT, 
		NON_NEGATIVE_INT, NON_NEGATIVE_INT_ARRAY, NORMALIZED_FLOAT, 
		NORMALIZED_FLOAT_ARRAY, POSITIVE_FLOAT_ARRAY, ROTATION, 
		ROTATION_ARRAY, SCALE3, TEX_COORD_ARRAY, TEXTURE_NODE,
		TEXTURE_COORDINATE_NODE, URL_ARRAY

5.4.2.2 FieldObserver interface

The FieldObserver interface allows programmers to monitor individual fields for changes. FieldObservers may be registered with Fields (and their subclasses) using the addFieldObserver method of the Field class. FieldObservers may be unregistered using the removeFieldObserver method of Field.

Once a FieldObserver is registered, its onFieldChange method will be invoked every time the field's value changes. The FieldObserver may pass userData to the Field during the addFieldObserver method; this will be passed back as an argument of the onFieldChange method.

Note that fields can return a reference to the node that contains them, via the owner member variable. Knowing this makes it easy to perform operations on nodes when their fields change.

	methods
           onFieldChange   invoked by the monitored field when the field's
                           value changes. A reference to the field itself 
                           and userData are passed in as arguments.

5.4.2.3 Searcher interface

Searchers help find nodes: Programmers frequently need to find particular nodes within a given scene. Searchers provide a way to hunt inside a scene for one or all instances of a node. Searchers will search all nodes in a scene graph, even those lying below a Group node (or subclass) whose hidden field is set to TRUE.

Searchers return paths: Often it's not enough just to get a reference to a node. A more complete and unique way to describe a node is by providing an array of nodes, ordered from the top of the scene (the root) to the desired node (the leaf). Such an array is called a path, and contains the root, the leaf, and all nodes that lie in between the two, in order. Searchers return paths to nodes, and other interfaces use paths as well. Paths have the following advantages:

  • Paths contain all intermediary nodes: These intermediary nodes might be Group nodes (or subclasses), which lie between parent nodes and children nodes, Appearance nodes, which lie between Shape nodes and Texture/Material nodes, or Shape nodes, which lie between Group and Appearance/Geometry nodes.
  • Paths denote unique instances: If a node is instanced more than once in a scene (as when one tire is instanced four times in a car model), then a simple reference to the tire's geometry will not help specify which of the four nodes is being referred to. However, when paths are used, unique references can be specified as four different paths; each of these paths will have the same root and leaf nodes, but the intermediary nodes will be specified as unique sets of Groups (or subclasses) , and perhaps Shapes.
  • Paths permit calculation of transformation matrices: A common programming task is the calculation of a matrix that passes from a leaf node's coordinate space to world space. The Group node provides a method getMatrix that transforms between one parent/child level. So, given a path to a node, there is a clear way to calculate the transformation between root and world; just collect and multiply the matrices of all Groups that lie along the path.

Searching can be by reference, type, DEF name, or combinations: There are three ways in which a node may be sought. Searching by reference will find a given node below a scene root and return a path or paths connecting the root to that node. Searching by DEF name will find a node or nodes with the given name and return the appropriate path(s). And searching by type will find a node or nodes of the given type (e.g., "find me all Geometry nodes") and return the path(s). These three types of specification may be mixed and matched, so that, for example, you can find all Material nodes named "RED".

Searching can return either one or all paths: Often more than one node will satisfy the search requirements. The API provides two search methods: one returns a path to the first such node encountered, the other returns paths to all nodes found.

Methods: The Searcher interface contains the following methods:

	methods
           setNode 	Sets a particular node as a criterion for 
			searching. If NULL, then node references will not 
			be checked during searching.
           setDefName   Sets a particular DEF name as a criterion for
			searching. If NULL, then names will not be checked
			during searching.
           setType      Sets a particular node type, specified as a string,
			as a criterion for searching. If NULL, then node
			types will not be checked during searching.
           searchFirst  Searches for and returns a path to the first node
			encountered that satisfies the currently 
			established search criteria.
           searchAll    Searches for and returns paths to all nodes that
			satisfy the currently established search criteria.
			The return value is an array of paths.

5.4.2.4 Picker interface

Pickers allow programmers to intersect rays with a scene and find out which geometry they intersect. CoreShout3DViewer's getNewPicker method returns a newly allocated picker, initialized to work with the viewpoint, window size, and scene associated with that viewer.

Pickers intersect rays with the scene: Pickers take a ray and intersect it with the geometry in a scene. Pickers do not intersect with any Background textures or any nodes other than Geometry and its derived classes. They also do not intersect with nodes below any Group node that has a value of TRUE for its hidden field.

Rays can be view-based or geometric: Programmers can describe a ray by providing the (x,y) coordinates of a pixel in the window of the viewer associated with the Picker. Or, they may provide any general ray as a pair of (from, to) points, to be intersected with the scene.

Pickers enable selection: The Picker API permits programmers to use a mouse click (see DeviceListener) as a basis for building a view-based ray, then determine the frontmost geometry that the ray hits. This makes selection of the object below the cursor a simple operation.

Pickers enable direct manipulation: By incorporating the above selection mechanism with familiar click-drag-release paradigms, it is a straightforward task to implement direct manipulation elements like the VRML 97 PlaneSensors and TouchSensors.

Pickers enable some collision detection: Pickers are not restricted to view-based ray intersections. Programmers may intersect any ray they choose with the scene. This is the foundation for ray-based collision detection and response.

Pickers can do varying amounts of work: Picking can be computationally expensive. The Picker interface provides API to control the amount of work in three ways:

Pickers can pick Any, Closest, or All: Different situations require paths to 0, 1, or all geometry nodes picked by a given ray. Implementations may optimize picking based on this information, and so there are three ways to pick. The pickAny and pickAnyFromTo methods allow a simple boolean test of whether anything at all was hit by the ray. The pickClosest and pickClosestFromTo methods return only the path to the nearest geometry, while the pickAll and pickAllFromTo methods return all intersected geometry, ordered from front to back.

Pickers can pick sub-sections of a scene: Each Picker is associated with a CoreShout3DViewer. By default, picks are made by intersecting the given ray with the scene contained by that viewer. Pickers can intersect with other scene graphs if the picker's setScene method is invoked. Picking within a subset of a scene may be accomplished by a call to setPath. In this case, the picker will only calculate ray intersections with nodes below the last node in the path (the earlier nodes of the path are required to properly calculate a transformation matrix between the scene root and the path's final node.)

Pickers can return varying amounts of information: Information about the coordinate, normal, and transformation matrix at the point of intersection are optional, as specified by the setPickInfo() method. These options provide clear opportunities for implementations to optimize the Picker's inner workings.

Methods: The Picker interface contains the following methods:

	methods:
           setPickInfo    establishes whether the coordinate and/or normal 
			  (at the intersection), and/or the transformation 
			  matrix (between root and object space) should be 
			  calculated. If the Picker is instructed to 
			  calculate any of these, then the corresponding 
			  parameters may be retrieved, following the pick, 
			  by calling getPickInfo.
           setScene       establishes a new scene graph for the picker
			  to use for ray intersection. (By default, 
			  intesects with associated viewer's scene.)
           setPath        establishes a new path for the picker to use for
			  ray intersection. Attempts only to intersect the 
			  ray with nodes at or below the leaf (final) node 
			  of the path. Other nodes in the path are used only 
			  to collect transformation information, by calling 
			  getMatrix on Group nodes along the path. (By 
			  default, intesects with associated viewer's scene.)
           pickAny        given a pixel coordinate assumed to be in the 
			  viewer's window, returns a boolean stating whether 
			  any geometry in the scene was intersected by the 
			  ray passing from the eyepoint through the pixel.
			  The intersected coordinate and normal will never
			  be calculated, even if specified by setPickInfo.
           pickAnyFromTo  identical to pickAny, except that the input is
			  a pair of points describing a ray. The points 
			  are to be expressed in the root coordinate space
			  of the scene being intersected.
           pickClosest    identical to pickAny, but returns a path to the 
			  closest geometry (to the ray's origin) that was 
			  intersected by the ray.
           pickClosestFromTo identical to pickClosest, but takes a geometric
			  from/to ray as input. 
           getPickInfo    If setPickInfo was used to specify that a 
			  coordinate, normal, and/or matrix should be 
			  calculated, this may be called after picking to 
			  return these values. Note that if pickAny or
			  pickAnyFromTo is used to pick, this method will
			  return more than one coordinate, normal, or 
			  matrix.  These values will be stored in sequence
			  within the returned array of floats. The order
			  will correspond to the order of the paths returned
			  from pickAll or pickAllFromTo.

5.4.2.5 Renderer and RenderObserver

These two interfaces control the rendering of a scene. The Renderer renders a given node or path. Each CoreShout3DViewer returns a reference to its renderer from the viewer's getRenderer method. This is the renderer used by the viewer to render its scene.

Registered RenderObservers are notified before and after the Renderer performs rendering, each time it renders, through calls to their onPreRender and onPostRender methods, respectively.

Interface: Renderer

The Renderer interface renders a given scene or path, and notifies any registered RenderObservers before and after rendering.

	methods
           render  	  renders the given node and all nodes below it.
			  Notifies RenderObservers before and after.
           renderPath	  renders only the leaf (final) node of the given
			  path and all nodes below that leaf. The other
			  nodes in the path are used only to collect
			  transformation space information by collecting 
			  the matrices of all Group nodes along the path.
			  Notifies RenderObservers before and after.
           addRenderObserver registers a passed in RenderObserver with this 
			  Renderer, with associated userData
           removeRenderObserver    unregisters the passed RenderObserver from 
			  monitoring this renderer.

Interface: RenderObserver

The RendererObserver interface is used to monitor a Renderer. A RenderObserver may register to be called back before and after each render, through the Renderer's addRenderObserver method. Renderers call the onPreRender method of all registered RenderObservers immediately prior to rendering (whether initiated by the render or renderPath method). Renderers call the onPostRender method of all registered observers immediately following the render.

	methods
           onPreRender    invoked on this interface by a Renderer  
			  immediately prior to rendering.  
           onPostRender   invoked on this interface by a Renderer upon 
			  completion of rendering.  

5.4.2.6 ResourceListener and ResourceObserver interfaces

In order to display a 3D scene, implementations may need to load the contents of various files, such as a Shout3D scene file or texture images used in rendering geometry. Such files are called resources. These two interfaces provide a mechanism whereby applications may request to be notified when loading of resources has been completed.

These interfaces enable programmers to time their actions. For example, programmers may wish to wait until a scene is completely loaded before attempting to display any geometry, choosing instead to display an alternative image or animation. Or they might wish to render a particular piece of geometry in a special color until such time as a texture is completely loaded. The resource interfaces enable programmers to be notified at these times and hence coordinate the behavior of their applications.

Each CoreShout3DViewer returns a reference to its resourceListener from the viewer's getResourceListener method. All ResourceObservers that register with this listener will be notified whenever the viewer completes the loading of a resource.

Interface: ResourceListener

The ResourceListener interface contains two methods for adding and removing ResourceObservers.

	methods
           addResourceObserver    registers a passed in ResourceObserver, 
			          with associated userData.
           removeResourceObserver unregisters the passed ResourceObserver.	

Interface: ResourceObserver

The ResourceObserver interface contains one method, onLoadDone. This method is called by the ResourceListener when it has finished loading its resource.

	methods
           onLoadDone   invoked on this interface by a ResourceListener 
			when a ResourceListener has finished loading its 
			resource. The method takes a string parameter which 
			is the name of the resource being loaded. This is 
			typically a file name. It also passes a boolean 
			parameter which specifies whether the loading was 
			successful.

5.4.2.7 DeviceListener and DeviceObserver interfaces

These two interfaces allow applications to monitor input from devices such as the mouse, keyboard, and window. The DeviceListener watches for system-dependent events and creates instances of DeviceInputs, such as MouseInput, KeyboardInput and WindowInput. It then calls the onDeviceInput method of all registered DeviceObservers.

Programmers can extend the API to monitor other kinds of devices, such as a joystick. First, a new subclass of DeviceInput must be implemented that contains the information unique to that device. Then, an implementation of the DeviceListener must be created that additionally watches for system-dependent inputs from this new device. The new DeviceListener should then call all registered DeviceObservers, passing an instance of the new subclass to all registered DeviceObservers.

Each CoreShout3DViewer returns a reference to its deviceListener from the viewer's getDeviceListener method. All DeviceObservers that register with this listener will be notified whenever the viewer's deviceListener receives input.

Interface: DeviceListener

The DeviceListener interface contains two methods for adding and removing DeviceObservers.

	methods
           addDeviceObserver     registers a passed in DeviceObserver, with
			         associated userData. An input argument, 
			         typeName, allows observers to listen to only 
			         certain subclasses of event
           removeDeviceObserver  unregisters the passed DeviceObserver.

Interface: DeviceObserver

The DeviceObserver interface contains one method, onDeviceInput. This method is called by the DeviceListener each time it processes input from a device.

	methods
           onDeviceInput   invoked on this interface by a DeviceListener
			   each time it processes an event. Returns TRUE
			   if this observer responds to the input, 
			   FALSE otherwise.

5.4.2.8 CoreShout3DViewer and Clock

The CoreShout3DViewer interface The CoreShout3DViewer stores the scene, which may be either loaded from a URL or passed as a reference to the scene's root node. It also returns references to the various interfaces for listening, picking, searching, and the clock. The Clock interface serves as the main time source for the viewer.

Interface: CoreShout3DViewer

This interface "owns" the scene and the renderer, providing access to both. The scene may be set either by loading an URL or by passing in the scene root. Programmers may ask for nodes in the current scene by DEF name, and can get access to Pickers, Searchers, Listeners, and the viewer's Clock.

	methods
           loadURL       reads the the file referred to by the
		 	 given URL and sets the passed root parameter to be
		         the root of the scene in that file.  Throws an 
			 exception if a scene can not be loaded from this 
			 URL. Registered ResourceObservers will be notified, 
			 through their onLoadDone method, once the scene is 
			 completely loaded. The passed root parameter is not 
			 guaranteed to contain the new scene until after the 
			 onLoadDone method has been called.
           setSceneFromURL  loads the scene from the file referred to by the
		 	 given URL.  Throws an exception if a scene can not
			 be loaded from this URL. Registered 
			 ResourceObservers will be notified, through their 
			 onLoadDone method, once the scene is completely 
			 loaded. The viewer's scene is not guaranteed to 
			 contain the new scene until after the onLoadDone 
			 method has been called.
           setScene    	 sets the scene to that given by the input node,
			 which will become the new scene root.
           getClock 	 returns a reference to the viewer's Clock.
           getCurrentBindableNode takes a string specifying a subclass of 
			 Bindable node as input. Returns a reference to the 
			 currently bound node of that type. Throws an 
			 exception if the input type is not a bindable class 
			 of node.
           getDeviceListener returns a reference to 
			 the viewer's DeviceListener
           getNewPicker  returns a new Picker, set up to work with this 
			 viewer.
           getNodeByName given a string denoting a DEF name, returns a node
			 that has that name.  Returns null if no
			 such node exists in the current scene.
           getRenderer      returns a reference to the viewer's renderer.
           getResourceListener returns a reference to the viewer's 
			 ResourceListener.
           getScene    	 returns a reference to the root of the current 
			 scene.
           getSearcher      returns a new Searcher.
           getVersion       returns a string denoting the version of this 
			 viewer. The format of the returned string is yet 
			 to be determined.
	

Interface: Clock

The Clock interface serves as the main source of time in Shout3D. At least once per render, the Clock's tick method must be invoked to set a new time in the clock. The time returned by getAbsolute time is the time that was set during the most recent call to tick.

	methods
           tick    This method updates the Clock and sets a new absolute time.
		   This method must be automatically invoked once per
		   call to Renderer.render(). This method may also be invoked
		   by a programmer whenever a new simulation tick is desired.
           getAbsoluteTime this method gets the number of seconds since 
		   midnight GMT January 1, 1970, as of the last call to tick().


Copyright� 1999-2000, Shout Interactive, Inc.